#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h> //struct sockaddr_in
#include <arpa/inet.h>  //inet_ntoa()  inet_addr()
#include <unistd.h>     //close()
#include <cstring>
using namespace std;
/*
广播是基于UDP的
为了防止广播轰炸占用网络资源，想发送广播需要先设置套接字选项申请广播权限
只要在同一局域网下的主机并且使用端口号一样都可以收到广播消息
xxx.xxx.xxx.255 是广播地址(主机序都是255就是广播地址)

流程：
1、socket：创建用于发送数据的套接字文件描述符
2、setsockopt：设置套接字属性，允许广播  SOL_SOCKET层  中 SO_BROADCAST
3、bind：可以绑定也可以不绑定
4、数据收发，对端套接字地址信息结构体
IP：广播地址
PORT：与接收端保持一致
5、sendto/recvfrom：数据收发
6、close：关闭套接字
*/
int main(int argc, const char *argv[])
{
    // 1、创建用于通信的客户端套接字文件描述符
    int sndfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sndfd == -1)
    {
        perror("socket error");
        return -1;
    }
    printf("socket success cfd = %d\n", sndfd);
    // 设置允许广播
    int broad = 1;
    // 要设置的值
    if (setsockopt(sndfd, SOL_SOCKET, SO_BROADCAST, &broad, sizeof(broad)) == -1)
    {
        perror("setsockopt error");
        return -1;
    }
    printf("成功设置广播\n");
    // 2、可以绑定也可以不绑定
    // 3、数据收发
    char wbuf[128] = "";
    // 填充接收端的地址信息结构体
    struct sockaddr_in rin;
    rin.sin_family = AF_INET;
    // 3
    // 通信域
    rin.sin_port = htons(8888);                         // 端口号
    rin.sin_addr.s_addr = inet_addr("192.168.174.255"); // 广播ip地址
    while (1)
    {
        // 清空容器
        bzero(wbuf, sizeof(wbuf));
        // 从终端读取数据
        fgets(wbuf, sizeof(wbuf), stdin);
        wbuf[strlen(wbuf) - 1] = '\0';
        // 将数据发送给服务器
        sendto(sndfd, wbuf, strlen(wbuf), 0, (struct sockaddr *)&rin, sizeof(rin));
        printf("发送成功\n");
    }
    // 4、关闭套接字
    close(sndfd);
    std::cout << "Hello, World!" << std::endl;
    return 0;
}